<?php

namespace app\components;

use Yii;
use yii\web\Cookie;
use app\models\RedisStore;
use app\models\WechatSdk;

class Tool
{
    const HTTP_GET_SUCCESS = 0;

    /**
     * 获取32位随机字符串
     * @return string
     */
    public function getRandKey()
    {
        return md5( time() . rand(1000, 99999999) );
    }

    /**
     * 获取随机6位数字
     * @return int
     */
    public function getRandNum()
    {
        return rand(100000, 999999);
    }

    /**
     * @param int $len
     * @return string
     */
    public function randString($len = 32)
    {
        $str = '';
        $primary_str = 'R_TYUIOP123ZXCVBcvb-nmlkjNMLy67KJHGFDSAQWE45ert89zxhgfdsaqwuiop';
        $primary_len = strlen($primary_str) - 1;
        for($i = 0; $i < $len; $i ++) {
            $rand_num = mt_rand(0, $primary_len);
            $str .= $primary_str[$rand_num];
        }
        return $str;
    }

    /**
     * @param $password
     * @param string $sign
     * @return string
     */
    public function getUserPassword($password, $sign = '')
    {
        return md5($sign . md5($password) . $sign);
    }

    /**
     * 金额显示
     * @param $money
     * @return string
     */
    public function moneyFormat($money)
    {
        if (is_int($money / 100)) {
            return number_format($money / 100, 1);
        } else {
            return number_format($money / 100, 2);
        }
    }

    /**
     * 金额显示
     * @param $money
     * @return string
     */
    public function moneyFormatYuan($money)
    {
        if (is_int($money / 100)) {
            return number_format($money / 100, 0, '.', '');
        } else {
            return number_format($money / 100, 2, '.', '');
        }
    }

    /**
     * 显示文件大小
     * @param $size
     * @return string
     */
    public function formatSize($size)
    {
        //兼容之前按字符串填写的格式
        if (empty($size) || stripos($size, 'M') !== false) {
            return $size;
        }

        return Yii::$app->formatter->asShortSize($size, 0);
    }

    public function getIp()
    {
        $ip = '';
        $ip_client = getenv('HTTP_CLIENT_IP') ? getenv('HTTP_CLIENT_IP') : '';
        $ip_x = getenv('HTTP_X_FORWARDED_FOR') ? getenv('HTTP_X_FORWARDED_FOR') : '';
        if ($ip_x) {
            $addrs = explode(",", $ip_x);
            $ip_x = $addrs[sizeof($addrs)-1];
        }
        $ip_remote = getenv('REMOTE_ADDR') ? getenv('REMOTE_ADDR') : '';

        if(!empty($ip_client) && filter_var($ip_client, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE) !== false)
        {
            $ip = $ip_client;
        }

        if(empty($ip) && ! empty($ip_x) && filter_var($ip_x, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE) !== false)
        {
            $ip = $ip_x;
        }

        if(empty($ip) && ! empty($ip_remote) && filter_var($ip_remote, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE) !== false)
        {
            $ip = $ip_remote;
        }

        return $ip;
    }

    /**
     * 临时设置日志文件
     * @param $file_name
     * @return bool
     */
    public function setLogFile($file_name)
    {
        $file_name .= '_' . date('Ymd');
        if (isset(Yii::$app->log->targets[0]->logFile)) {
            Yii::$app->log->targets[0]->logFile = LOG_PATH . $file_name . '.log';
            return true;
        }

        return false;
    }

    /**
     * @param $url
     * @return mixed
     */
    public function httpGet($url, $timeout = 5)
    {
        $ret = [
            'errno' => self::HTTP_GET_SUCCESS,
            'error' => '',
            'data' => '',
            'http_code' => 0,
        ];
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_MAXREDIRS, 1);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 QianZhuangApi/2.0");
        curl_setopt($ch, CURLOPT_URL, $url);

        $data = curl_exec($ch);

        $httpStatus = curl_getinfo($ch);
        $ret['http_code'] = $httpStatus['http_code'];

        if (empty($data)) {
            $ret['errno'] = 1;
            $ret['error'] = curl_error($ch);
        } else {
            $ret['data'] = $data;
        }
        curl_close($ch);

        return $ret;
    }

    public function httpPost($url, $data, $type = 'form', $timeout = 5)
    {
        $ret = [
            'errno' => 0,
            'error' => '',
            'data' => '',
            'http_code' => 0,
        ];

        if ($type == 'raw') {
            $post_data = http_build_query($data);
        } elseif ($type == 'json') {
            $post_data = json_encode($data);
        } elseif ($type == 'header_auth') {
            $header_auth_token = $data['header_auth_token'];
            unset($data['header_auth_token']);
            $post_data = json_encode($data);
        } else {
            $post_data = $data;
        }

        $ch = curl_init();

        if ($type == 'json') {
            curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json; charset=utf-8', 'Content-Length: ' . strlen($post_data)));
        }

        if ($type == 'header_auth') {
            $header_auth_token_str = 'token:' . $header_auth_token;
            curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Accept:application/json', $header_auth_token_str));
        }

        if ($type == 'header_doumi_auth') {
            if (isset($data['header_auth'])) {
                $header_auth_token_str = 'Authorization:' . $data['header_auth'];
                curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept:application/vnd.doumi.v1+json', 'Content-Type: application/json', $header_auth_token_str));
                unset($data['header_auth']);
            } else {
                curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept:application/vnd.doumi.v1+json', 'Content-Type: application/json'));
            }

            $post_data = json_encode($data);
        }

        if ($type == 'header_certificate') {
            curl_setopt($ch, CURLOPT_HTTPHEADER, array('certification:7000deb1d3d591092a3fc0ce341e9d4b'));
        }

        if ($type == 'header_auth_md5') {
            $time_sign = time();
            curl_setopt($ch, CURLOPT_HTTPHEADER, array('APP-KEY:ASO10000','APP-TIMESTAMP:' . time(), 'APP-SIGNATURE:' . md5('ASO10000' . '06933f0448a07c636cc25ce15e6a028a' . $time_sign)));
        }

        curl_setopt ( $ch,CURLOPT_TIMEOUT, $timeout);
        //curl_setopt ( $ch,CURLOPT_VERBOSE, 1);
        curl_setopt ( $ch, CURLOPT_URL, $url );
        curl_setopt ( $ch, CURLOPT_POST, 1 );
        curl_setopt ( $ch, CURLOPT_HEADER, 0 );
        curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
        curl_setopt ( $ch, CURLOPT_USERAGENT, "Mozilla/5.0 QianZhuangApi/2.0");
        curl_setopt ( $ch, CURLOPT_POSTFIELDS, $post_data );

        $data = curl_exec($ch);

        $httpStatus = curl_getinfo($ch);
        $ret['http_code'] = $httpStatus['http_code'];

        if (empty($data)) {
            $ret['errno'] = 1;
            $ret['error'] = curl_error($ch);
        } else {
            $ret['data'] = $data;
        }
        curl_close($ch);

        return $ret;
    }

    /**
     * 动态绑host的curl请求方法
     * @param $host array 需要配置的域名 array("Host: appems.com");
     * @param $data string 需要提交的数据
     * @param $url string 要提交的url
     * @return int|mixed
     */
    public function httpPostDynamic($host, $url, $data)
    {
        $ch = curl_init();
        curl_setopt ( $ch, CURLOPT_TIMEOUT, 5);
        //curl_setopt ( $ch, CURLOPT_VERBOSE, 1);
        curl_setopt ( $ch, CURLOPT_URL, $url);
        curl_setopt ( $ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt ( $ch, CURLOPT_HEADER, 0);
        curl_setopt ( $ch, CURLOPT_POST, 1);
        curl_setopt ( $ch, CURLOPT_USERAGENT, "Mozilla/5.0 QianZhuangApi/2.0");
        curl_setopt ( $ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt ( $ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt ( $ch, CURLOPT_HTTPHEADER, $host);
        $result = curl_exec($ch);
        //$info = curl_getinfo($ch);
        //var_dump($info);
        curl_close($ch);
        if ($result == NULL) {
            return 0;
        }
        return $result;
    }

    /*
     * 日志方法
     */
    public function logWrite($name, $content, $tips = '')
    {
        if (empty($name) || empty($content)) {
            return false;
        }

        $redis = new RedisStore();
        $data = [
            'logName' => $name,
            'content' => $content,
            'tips' => $tips,
        ];
        return $redis->pushQueue(REDIS_WRITE_LOG_KEY, json_encode($data, JSON_UNESCAPED_UNICODE));
    }

    /**
     * 将数组导出csv格式，直接下载
     * @param array $arr
     */
    public function exportCsv($arr = [], $attachname = 'export-data')
    {
        header("Content-Type: text/csv");
        header("Content-Disposition: attachment;filename=$attachname.csv");
        $fp = fopen('php://output', 'w');
        foreach ($arr as $row) {
            fputcsv($fp, $row);
        }
        fclose($fp);
        exit;
    }

    /**
     * 验证手机号码格式
     * @param $mobile
     * @return bool
     */
    public function isMobile($mobile)
    {
        // $mobile = intval($mobile);

        if (strlen($mobile) != 11) {
            return false;
        }

        if (substr($mobile, 0, 1) != 1) {
            return false;
        }

        return true;
    }

    /**
     * 比较两个字符串（区分大小写）：
     * true 如果两个字符串相等
     * true 如果 string1 小于 string2
     * false 如果 string1 大于 string2
     * @param $string1 拿来作对比的目标字串
     * @param $string2 当前需对比的字串
     * 场景示例：$string1 版本达到1.2.2的app才支持分享功能 $string2 该用户当前app版本
     * $string1 = '1.2.2'; $string2 = '1.1.8';//对比结果为false
     * $string1 = '1.2.2'; $string2 = '1.2.2';//true
     * $string1 = '1.2.2'; $string2 = '1.3.0';//true
     * @return bool
     */
    public function compareString($string1, $string2)
    {
        return strcmp($string1, $string2) <= '0' ? true : false;
    }

    /**
     * 获取当天结束时间与当前时间的时间戳的差值
     * @return int
     */
    public function nowToEnd()
    {
        $now = time();
        $end = mktime(23, 59, 59, date("m"), date("d"), date("Y"));

        $timeZone = $end - $now;

        return $timeZone;
    }

    /**
     * 毫秒转秒
     * @param $millisecond 毫秒
     * @return int
     */
    public function toSecond($millisecond)
    {
        $second = floor($millisecond / 1000);
        return (int)$second;
    }

    /**
     * 获取sign
     * @param $params
     * @param $secret_key
     * @return string
     */
    public function getSigns($params, $secret_key)
    {
        /**
         * 内部函数递归排序数组
         * @param $arr
         * @return array
         */
        $sortArray = function (&$arr) use (&$sortArray) {
            if (!empty($arr) && is_array($arr)) {
                ksort($arr);   //字典序
                foreach ($arr as $k => $v) {
                    if (empty($v) && 0 != $v) {
                        continue;
                    }
                    if (is_array($v)) {
                        return $sortArray($arr[$k]);
                    }
                }
                return $arr;
            }
        };
        $sortArray($params);
        reset($params);
        //把数组所有元素，按照“参数=参数值”的模式拼接成字符串
        $str = '';
        foreach ($params as $k => $v) {
            if (is_array($v)) {
                ksort($v);
                $v = json_encode($v, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
            }
            $str .= $k . '=' . $v;
        }
        $str .= $secret_key;
        return md5($str);
    }

    /**
     * @param        $text          需进行format的内容
     * @param string $replace_str   需对内容进行format的字符
     *
     * @return mixed
     */
    public function formatDoubleStr($text, $replace_str = " ")
    {
        $text = trim($text);
        $double_replace_str = $replace_str . $replace_str;
        while (stripos($text, $double_replace_str) !== false) {
            $text = str_replace($double_replace_str, $replace_str, $text);
        }
        return $text;
    }

    public function httpGetHead($url, $param, $timeout = 5)
    {
        $ret = [
            'errno' => self::HTTP_GET_SUCCESS,
            'error' => '',
            'data' => '',
            'http_code' => 0,
        ];
        $ch = curl_init();

        $header_auth_token_str = 'Authorization:' . $param['header_auth'];

        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept:application/vnd.doumi.v1+json', $header_auth_token_str));

        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_MAXREDIRS, 1);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 QianZhuangApi/2.0");
        curl_setopt($ch, CURLOPT_URL, $url);

        $data = curl_exec($ch);

        $httpStatus = curl_getinfo($ch);
        $ret['http_code'] = $httpStatus['http_code'];

        if (empty($data)) {
            $ret['errno'] = 1;
            $ret['error'] = curl_error($ch);
        } else {
            $ret['data'] = $data;
        }
        curl_close($ch);

        return $ret;
    }

    /**
     * @param $in
     *
     * @return string
     */
    public function base64url_encode($in)
    {
        return rtrim(strtr(base64_encode($in), '+/', '-_'), '=');
    }

    /**
     * 添加cookie
     * @param string $name
     * @param string $value
     */
    public function addCookie($name, $value, $expire = 0)
    {
        $cookies = Yii::$app->response->cookies;
        $cookies->add(
            new Cookie([
                'name' => $name,
                'value' => $value,
                'expire' => time() + $expire,
                'domain' => COOKIE_DOMAIN,
            ])
        );
    }

    /**
     * 删除cookie
     * @param string $name
     */
    public function delCookie($name)
    {
        $cookies = Yii::$app->response->cookies;
        $cookies->add(
            new Cookie([
                'name' => $name,
                'expire' => time() - COOKIE_EXPIRE_TIME,
                'domain' => COOKIE_DOMAIN,
            ])
        );
    }

    /**
     * @param int $errno
     * @param string $error
     * @param array $data
     * @return array
     */
    public function respData($errno = 0, $error = 'ok', $data = [])
    {
        return [
            'errno' => $errno,
            'error' => $error,
            'data' => $data
        ];
    }

    /**
     * @param int $errno
     * @param string $error
     * @param array $data
     * @return string
     */
    public function respJsonData($errno = 0, $error = 'ok', $data = [])
    {
        return json_encode($this->respData($errno, $error, $data), JSON_UNESCAPED_UNICODE);
    }

    /**
     * 中文汉字截取无乱码
     * @param $string
     * @param $start
     * @param $length
     * @return string
     */
    function GBsubstr($string, $start, $length, $encoding = 'utf-8')
    {
        if(mb_strlen($string, $encoding) > $length){
            $str = null;
            $len = $start + $length;
            for($i = $start; $i < $len; $i++){
                if(ord(mb_substr($string, $i, 1)) > 0xa0){
                    $str .= mb_substr($string, $i, 2, $encoding);
                    $i++;
                }else{
                    $str .= mb_substr($string, $i, 1, $encoding);
                }
            }
            return $str . '...';
        }else{
            return $string;
        }
    }

    /**
     * 功能：字符串加密以及解密函数
     * @param string $string 原文或者密文
     * @param string $operation 操作(ENCODE | DECODE), 默认为 DECODE
     * @param string $key 密钥
     * @param int $expiry 密文有效期, 加密时候有效， 单位 秒，0 为永久有效
     * @return string            处理后的 原文或者 经过 base64_encode 处理后的密文 *
     * @example *
     *    $a = authcode('abc', 'ENCODE', 'key');
     *    $b = authcode($a, 'DECODE', 'key');  // $b(abc) *
     *    $a = authcode('abc', 'ENCODE', 'key', 3600);
     *    $b = authcode('abc', 'DECODE', 'key'); // 在一个小时内，$b(abc)，否则 $b 为空
     */
    public function encrypt_code($string, $operation = 'DECODE', $key = '', $expiry = 0)
    {
        $ckey_length = 4;    // 随机密钥长度 取值 0-32;
        // 加入随机密钥，可以令密文无任何规律，即便是原文和密钥完全相同，加密结果也会每次不同，增大破解难度。
        // 取值越大，密文变动规律越大，密文变化 = 16 的 $ckey_length 次方
        // 当此值为 0 时，则不产生随机密钥
        $key = md5($key ? $key : TOOL_ENCRYPT_SECRET_CODE);//$可传自定义key
        $keya = md5(substr($key, 0, 16));
        $keyb = md5(substr($key, 16, 16));
        $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : '';

        $cryptkey = $keya . md5($keya . $keyc);
        $key_length = strlen($cryptkey);

        $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;
        $string_length = strlen($string);

        $result = '';
        $box = range(0, 255);

        $rndkey = array();
        for ($i = 0; $i <= 255; $i++) {
            $rndkey[$i] = ord($cryptkey[$i % $key_length]);
        }

        for ($j = $i = 0; $i < 256; $i++) {
            $j = ($j + $box[$i] + $rndkey[$i]) % 256;
            $tmp = $box[$i];
            $box[$i] = $box[$j];
            $box[$j] = $tmp;
        }

        for ($a = $j = $i = 0; $i < $string_length; $i++) {
            $a = ($a + 1) % 256;
            $j = ($j + $box[$a]) % 256;
            $tmp = $box[$a];
            $box[$a] = $box[$j];
            $box[$j] = $tmp;
            $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
        }

        if ($operation == 'DECODE') {
            if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) {
                return substr($result, 26);
            } else {
                return '';
            }
        } else {
            return $keyc . str_replace('=', '', base64_encode($result));
        }
    }
}
